Normalize:
- Exceptions that are not
Error
instances - Error properties (
name
, message
, stack
, constructor
) that are
missing, invalid,
enumerable, readonly,
non-writable,
non-configurable,
non-extensible, proxied or
throwing error.cause
and
error.errors
recursively, when present
Example
import normalizeException from 'normalize-exception'
try {
throw 'message'
} catch (error) {
console.log(error)
console.log(normalizeException(error))
console.log(normalizeException(error) instanceof Error)
}
Install
npm install normalize-exception
This package works in both Node.js >=14.18.0 and
browsers.
It is an ES module and must be loaded using
an import
or import()
statement,
not require()
.
API
normalizeException(error, options?)
error
any
options
Options
Return value: Error
normalizeException()
never throws.
If error
is an Error
instance, it is returned. Any missing or invalid error
property is directly modified.
If it is not an Error
instance, a new one is created and returned.
Options
Options are an optional object with the following properties.
shallow
Type: boolean
Default: false
Unless true
,
error.cause
and
error.errors
are normalized recursively, when present.
Features
Invalid type
Strings
try {
throw 'message'
} catch (error) {
console.log(error)
console.log(normalizeException(error))
console.log(normalizeException(error) instanceof Error)
}
Plain objects
try {
throw { name: 'TypeError', message: 'message' }
} catch (error) {
console.log(normalizeException(error))
}
Others
try {
throw null
} catch (error) {
console.log(error.message)
console.log(normalizeException(error).message)
}
Missing properties
try {
const error = new TypeError('message')
error.name = undefined
throw error
} catch (error) {
console.log(error.name)
console.log(normalizeException(error).name)
}
Mismatched constructor
try {
const error = new TypeError('message')
error.constructor = RangeError
throw error
} catch (error) {
console.log(error.constructor)
console.log(normalizeException(error).constructor)
}
Missing stack
try {
const error = new Error('message')
error.stack = undefined
throw error
} catch (error) {
console.log(error.stack)
console.log(normalizeException(error).stack)
}
Invalid properties
try {
const error = new Error('message')
error.message = true
throw error
} catch (error) {
console.log(typeof error.message)
console.log(typeof normalizeException(error).message)
}
Enumerable properties
class ExampleError extends Error {
constructor(...args) {
super(...args)
this.name = 'ExampleError'
}
}
try {
throw new ExampleError('message')
} catch (error) {
console.log({ ...error })
console.log({ ...normalizeException(error) })
}
Readonly properties
try {
const error = new Error('message')
Object.defineProperty(error, 'message', { get: () => 'message' })
throw error
} catch (error) {
error.message = 'other'
normalizeException(error).message = 'other'
}
Non-writable properties
try {
const error = new Error('message')
Object.defineProperty(error, 'message', { value: '', writable: false })
throw error
} catch (error) {
error.message = 'other'
normalizeException(error).message = 'other'
}
Non-configurable properties
try {
const error = new Error('message')
Object.defineProperty(error, 'message', { value: '', configurable: false })
throw error
} catch (error) {
delete error.message
delete normalizeException(error).message
}
Non-extensible error
try {
const error = new Error('message')
Object.preventExtensions(error)
throw error
} catch (error) {
error.prop = true
normalizeException(error).prop = true
}
Proxies
try {
throw new Proxy(new Error('message'), {})
} catch (error) {
const { toString } = Object.prototype
console.log(toString.call(error))
console.log(toString.call(normalizeException(error)))
}
Throwing properties
Proxies
try {
throw new Proxy(new Error('message'), {
get() {
throw new Error('example')
},
})
} catch (error) {
console.log(error.message)
console.log(normalizeException(error).message)
}
Getters
try {
const error = new Error('message')
Object.defineProperty(error, 'message', {
get() {
throw new Error('example')
},
})
throw error
} catch (error) {
console.log(error.message)
console.log(normalizeException(error).message)
}
Recursion
error.cause
try {
throw new Error('message', { cause: 'innerError' })
} catch (error) {
console.log(error.cause instanceof Error)
console.log(normalizeException(error).cause instanceof Error)
}
error.errors
try {
throw new AggregateError(['innerError'], 'message')
} catch (error) {
console.log(error.errors[0] instanceof Error)
console.log(normalizeException(error).errors[0] instanceof Error)
}
Related projects
Support
For any question, don't hesitate to submit an issue on GitHub.
Everyone is welcome regardless of personal background. We enforce a
Code of conduct in order to promote a positive and
inclusive environment.
Contributing
This project was made with ❤️. The simplest way to give back is by starring and
sharing it online.
If the documentation is unclear or has a typo, please click on the page's Edit
button (pencil icon) and suggest a correction.
If you would like to help us fix a bug or add a new feature, please check our
guidelines. Pull requests are welcome!